package com.spider.gp.config;

import com.alibaba.excel.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.spider.gp.dao.SqlStatementExecution;
import com.spider.gp.dao.SqlStatementExecutionDao;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronSequenceGenerator;
import org.springframework.scheduling.support.CronTrigger;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;

/**
 * description: 先注册，后执行(根据返回的时间执行)
 * @author clare
 * @date 2022/9/22
 **/

@EnableScheduling
@Slf4j
@Configuration
public class TaskConfig implements SchedulingConfigurer {
    @Autowired
    private SqlStatementExecutionDao dao;

    private final ConcurrentHashMap<String, ScheduledFuture<?>> scheduledFutures = new ConcurrentHashMap<>();
    private final ConcurrentHashMap<String, SqlStatementExecution> timerConfigMap = new ConcurrentHashMap<>();
    private volatile ScheduledTaskRegistrar registrar;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskrRegistrar) {
        //定时任务开启
        List<SqlStatementExecution> crons = dao.selectList(new LambdaQueryWrapper<>());
        //设置线程,默认单线程
        taskrRegistrar.setScheduler(Executors.newScheduledThreadPool(2));
        this.registrar = taskrRegistrar;
        refresh(crons);
    }

    public void refresh(List<SqlStatementExecution> timerConfigs) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");

        if (timerConfigs != null) {
            for (SqlStatementExecution timerConfig : timerConfigs) {
                //定时任务cron表达式
                String cron = timerConfig.getCronExecution();
                String fixLogo = timerConfig.getFixLogo();
                //如果是空则跳过
                if (StringUtils.isEmpty(cron)) {
                    continue;
                }
                //计划任务已经存在并且未发生变化，跳过
                if (scheduledFutures.containsKey(timerConfig.getFixLogo())
                        && timerConfigMap.get(timerConfig.getCronExecution()).equals(cron)) {
                    continue;
                }
                //如果任务cron发生变化，则取消当前任务
                if (scheduledFutures.containsKey(timerConfig.getFixLogo())) {
                    scheduledFutures.get(timerConfig.getFixLogo()).cancel(false);
                    scheduledFutures.remove(timerConfig.getFixLogo());
                    timerConfigMap.remove(timerConfig.getFixLogo());
                }
                final Date[] nextExecNew = {null};
                Trigger trigger =  new Trigger() {
                    @Override
                    public Date nextExecutionTime(TriggerContext triggerContext) {
                        CronTrigger trigger = new CronTrigger(cron);
                        Date nextExec = trigger.nextExecutionTime(triggerContext);
                        nextExecNew[0] = nextExec;
                        return nextExec;
                    }
                };
                ScheduledFuture<?> future = registrar.getScheduler().schedule(getRunnable(timerConfig), trigger);
                timerConfigMap.put(timerConfig.getFixLogo(), timerConfig);
                scheduledFutures.put(timerConfig.getFixLogo(), future);
                timerConfig.setNextTime(simpleDateFormat.format(nextExecNew[0]));
                dao.updateById(timerConfig);
            }
        }
    }

    private boolean exists(List<SqlStatementExecution> timerConfigs, String timerId) {
        for (SqlStatementExecution timerConfig : timerConfigs) {
            if (timerConfig.getFixLogo().equals(timerId)) {
                return true;
            }
        }
        return false;
    }


    /**
     * 获取Trigger
     *
     * @param
     * @return
     */
    private Trigger getTrigger(String cron) {
        return  new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                CronTrigger trigger = new CronTrigger(cron);
                Date nextExec = trigger.nextExecutionTime(triggerContext);
                return nextExec;
            }
        };
    }


    private Runnable getRunnable(SqlStatementExecution timerConfig) {

        return new Runnable() {
            @Override
            public void run() {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
                String cronExecution = timerConfig.getCronExecution();
                CronSequenceGenerator cronSequenceGenerator = new CronSequenceGenerator(cronExecution);

                SqlStatementExecution sqlStatementExecution = timerConfigMap.get(timerConfig.getFixLogo());
                LambdaQueryWrapper<SqlStatementExecution> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(SqlStatementExecution::getFixLogo , sqlStatementExecution.getFixLogo());
                SqlStatementExecution sqlStatementExecutionNew = dao.selectOne(wrapper);

                String sqlStatement = sqlStatementExecutionNew.getSqlStatement();
                dao.commonSql(sqlStatement);
                Date currentTime = new Date();
                Date nextTimePoint = cronSequenceGenerator.next(currentTime); // currentTime为计算下次时间点的开始时间
                timerConfig.setNextTime(simpleDateFormat.format(nextTimePoint));
                dao.updateById(timerConfig);
            }
        };
    }


//    @Override
//    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
//        //获取所有的定时任务
//        Map<String,BaskTask> map = applicationContext.getBeansOfType(BaskTask.class);
//
//        //遍历注册
//        for(String key :map.keySet()){
//            BaskTask baskTask = map.get(key);
//            //baskTask:回调内部的run方法
//            //baskTask.getCron() 获取各个任务的执行频率
//            scheduledTaskRegistrar.addTriggerTask(baskTask,sheduledConfig->{
//                Date date = new CronTrigger(baskTask.getCron()).nextExecutionTime(sheduledConfig);
//                log.info(key + "执行定时任务的时间:" + formatDate(date));
//                return date;
//            });
//        }
//    }
}








